package com.njtoyo.taxi.admin.service.data.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.mapper.master.entity.DriverMarketing;
import com.njtoyo.taxi.admin.mapper.master.enums.DriverMarketingSituation;
import com.njtoyo.taxi.admin.mapper.master.mapper.DriverMarketingMapper;
import com.njtoyo.taxi.admin.mapper.secondary.entity.cache.CacheAllowanceDriver;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.cache.CacheAllowanceDriverMapper;
import com.njtoyo.taxi.admin.rest.presenter.data.allowance.DriverAllowancePresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.allowance.DriverPeakAllowancePresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.allowance.DriverRecommendAllowancePresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.allowance.DriverRedPacketAllowancePresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.allowance.AllowanceChartWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.data.allowance.AllowanceWrapper;
import com.njtoyo.taxi.admin.service.data.AllowanceDriverService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@DS(Const.SECONDARY_DS)
public class AllowanceDriverServiceCacheImpl implements AllowanceDriverService {

    @Autowired
    private CacheAllowanceDriverMapper cacheAllowanceDriverMapper;

    @Autowired
    private DriverMarketingMapper driverMarketingMapper;

    @Override
    public RestResult<DriverAllowancePresenter> proportion(AdminUser adminUser, AllowanceWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartTime(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndTime(), DatePattern.NORM_DATE_PATTERN);
        DriverAllowancePresenter res = cacheAllowanceDriverMapper.getProportion(start, end);
        return RestResult.success(res);
    }

    @Override
    public RestResult<DriverRedPacketAllowancePresenter> redPacket(AdminUser adminUser, AllowanceWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartTime(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndTime(), DatePattern.NORM_DATE_PATTERN);
        DriverRedPacketAllowancePresenter res = cacheAllowanceDriverMapper.getRedPacket(start, end);

        return RestResult.success(res);
    }

    @Override
    public RestResult<DriverRecommendAllowancePresenter> recommend(AdminUser adminUser, AllowanceWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartTime(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndTime(), DatePattern.NORM_DATE_PATTERN);
        DriverRecommendAllowancePresenter res = cacheAllowanceDriverMapper.getRecommend(start, end);

        return RestResult.success(res);
    }

    @Override
    public RestResult<DriverPeakAllowancePresenter> peak(AdminUser adminUser, AllowanceWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartTime(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndTime(), DatePattern.NORM_DATE_PATTERN);
        DriverPeakAllowancePresenter res = cacheAllowanceDriverMapper.getPeak(start, end);

        // 当前开通城市
        QueryWrapper<DriverMarketing> marketingQueryWrapper = new QueryWrapper<>();
        marketingQueryWrapper.eq("situation", DriverMarketingSituation.online_ride_fixed)
                .eq("is_active", 1)
                .le("started_at", DateTime.now())
                .ge("ended_at", DateTime.now())
                .select("DISTINCT driver_region_id");

        List<Object> cityCount = driverMarketingMapper.selectObjs(marketingQueryWrapper);
        res.setCityCount((long) cityCount.size());

        return RestResult.success(res);
    }

    @Override
    public RestResult<List<DriverAllowancePresenter>> chartProportion(AdminUser adminUser, AllowanceChartWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartDate(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndDate(), DatePattern.NORM_DATE_PATTERN);

        QueryWrapper<CacheAllowanceDriver> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("stats_date", start, end)
                .select("stats_date, red_packet_opened + red_packet_unopened AS red_packet, peak_amount, recommend_amount");

        List<Map<String, Object>> allowances = cacheAllowanceDriverMapper.selectMaps(queryWrapper);
        Map<String, Map<String, Object>> allowanceMap = allowances.stream().collect(Collectors.toMap(e -> e.get("statsDate").toString(), e -> e));

        List<Date> dataList = this.getDataList(wrapper.getStartDate(), wrapper.getEndDate());
        ArrayList<DriverAllowancePresenter> list = new ArrayList<>();
        for (Date date : dataList) {
            DriverAllowancePresenter presenter = new DriverAllowancePresenter().setStartDate(date)
                    .setRedPacket(BigDecimal.ZERO).setOnlineOrder(BigDecimal.ZERO).setRecommend(BigDecimal.ZERO);
            String dateKey = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
            if (allowanceMap.containsKey(dateKey)) {
                Map<String, Object> data = allowanceMap.get(dateKey);
                presenter.setRedPacket((BigDecimal) data.getOrDefault("redPacket", 0))
                        .setOnlineOrder((BigDecimal) data.getOrDefault("peakAmount", 0))
                        .setRecommend((BigDecimal) data.getOrDefault("recommendAmount", 0));
            }
            list.add(presenter);
        }
        return RestResult.success(list);
    }

    @Override
    public RestResult<List<DriverRedPacketAllowancePresenter>> chartRedPacket(AdminUser adminUser, AllowanceChartWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartDate(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndDate(), DatePattern.NORM_DATE_PATTERN);

        QueryWrapper<CacheAllowanceDriver> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("stats_date", start, end)
                .select("stats_date, red_packet_opened, red_packet_unopened");

        List<Map<String, Object>> allowances = cacheAllowanceDriverMapper.selectMaps(queryWrapper);
        Map<String, Map<String, Object>> allowanceMap = allowances.stream().collect(Collectors.toMap(e -> e.get("statsDate").toString(), e -> e));

        List<Date> dataList = this.getDataList(wrapper.getStartDate(), wrapper.getEndDate());
        ArrayList<DriverRedPacketAllowancePresenter> list = new ArrayList<>();
        for (Date date : dataList) {
            DriverRedPacketAllowancePresenter presenter = new DriverRedPacketAllowancePresenter().setStartDate(date)
                    .setOpened(BigDecimal.ZERO).setUnopened(BigDecimal.ZERO);
            String dateKey = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
            if (allowanceMap.containsKey(dateKey)) {
                Map<String, Object> data = allowanceMap.get(dateKey);
                presenter.setOpened((BigDecimal) data.getOrDefault("redPacketOpened", 0))
                        .setUnopened((BigDecimal) data.getOrDefault("redPacketUnopened", 0));
            }
            list.add(presenter);
        }
        return RestResult.success(list);
    }

    @Override
    public RestResult<List<DriverRecommendAllowancePresenter>> chartRecommend(AdminUser adminUser, AllowanceChartWrapper wrapper) {
        String start = DateUtil.format(wrapper.getStartDate(), DatePattern.NORM_DATE_PATTERN);
        String end = DateUtil.format(wrapper.getEndDate(), DatePattern.NORM_DATE_PATTERN);

        QueryWrapper<CacheAllowanceDriver> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("stats_date", start, end)
                .select("stats_date, recommend_app_amount, recommend_app_count, recommend_wxmina_amount, recommend_wxmina_count");

        List<Map<String, Object>> allowances = cacheAllowanceDriverMapper.selectMaps(queryWrapper);
        Map<String, Map<String, Object>> allowanceMap = allowances.stream().collect(Collectors.toMap(e -> e.get("statsDate").toString(), e -> e));

        List<Date> dataList = this.getDataList(wrapper.getStartDate(), wrapper.getEndDate());
        ArrayList<DriverRecommendAllowancePresenter> list = new ArrayList<>();
        for (Date date : dataList) {
            DriverRecommendAllowancePresenter presenter = new DriverRecommendAllowancePresenter()
                    .setStartDate(date).setAppAmount(BigDecimal.ZERO).setAppCount(0L)
                    .setWxminaAmount(BigDecimal.ZERO).setWxminaCount(0L);
            String dateKey = DateUtil.format(date, DatePattern.NORM_DATE_PATTERN);
            if (allowanceMap.containsKey(dateKey)) {
                Map<String, Object> data = allowanceMap.get(dateKey);
                presenter.setAppAmount((BigDecimal) data.getOrDefault("recommendAppAmount", 0))
                        .setAppCount(Long.parseLong(data.getOrDefault("recommendAppCount", 0).toString()))
                        .setWxminaAmount((BigDecimal) data.getOrDefault("recommendWxminaAmount", 0))
                        .setWxminaCount(Long.parseLong(data.getOrDefault("recommendWxminaCount", 0).toString()));
            }
            list.add(presenter);
        }
        return RestResult.success(list);
    }

    private List<Date> getDataList(Date start, Date end) {
        List<Date> list = new ArrayList<>();
        list.add(start);
        while (start.before(end)) {
            start = DateUtil.offsetDay(start, 1);
            list.add(start);
        }
        return list;
    }
}
